home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ETO Development Tools 4
/
ETO Development Tools 4.iso
/
Tools - Objects
/
MacApp
/
MacApp 3.0a2
/
Libraries
/
UGridView.cp
< prev
next >
Wrap
Text File
|
1991-05-01
|
81KB
|
2,946 lines
// UGridView.cp
// Copyright © 1987-1991 by Apple Computer Inc. All rights reserved.
#ifndef __UGRIDVIEW__
#include <UGridView.h>
#endif
#ifndef __STDIO__
#include <StdIo.h>
#endif
#ifndef __UGEOMETRY__
#include <UGeometry.h>
#endif
#ifndef __ERRORS__
#include <Errors.h>
#endif
#ifndef __TOOLUTILS__
#include <ToolUtils.h>
#endif
#ifndef __PACKAGES__
#include <Packages.h>
#endif
#ifndef __STDLIB__
#include <StdLib.h>
#endif
#ifndef __UADORNERS__
#include <UAdorners.h>
#endif
#ifndef __UMACAPPUTILITIES__
#include <UMacAppUtilities.h>
#endif
#ifndef __UMEMORY__
#include <UMemory.h>
#endif
#ifndef __UMACAPPGLOBALS__
#include <UMacAppGlobals.h>
#endif
//--------------------------------------------------------------------------------------------------
RgnHandle pPixelsToHighlight;
RgnHandle pPreviousSelection;
RgnHandle pDifference;
RgnHandle pVisibleCells;
RgnHandle pInvalidateRgn;
//--------------------------------------------------------------------------------------------------
#pragma segment GVInit
pascal void InitUGridView(void)
{
if (qTemplateViews)
{
// So the linker doesn't dead strip these
if (gDeadStripSuppression)
{
DontDeadStrip(TGridView);
DontDeadStrip(TTextGridView);
DontDeadStrip(TTextListView);
}
RegisterStdType("TGridView", kStdGridView);
RegisterStdType("TTextGridView", kStdTextGridView);
RegisterStdType("TTextListView", kStdTextListView);
}
pPixelsToHighlight = MakeNewRgn();
pPreviousSelection = MakeNewRgn();
pDifference = MakeNewRgn();
pVisibleCells = MakeNewRgn();
pInvalidateRgn = MakeNewRgn();
gUGridViewInitialized = TRUE;
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVOpen
pascal void TRunArray::Initialize(void) // override
{
inherited::Initialize();
fChunks = NULL;
fLastChunk = 0;
fLastIndex = 1;
fLastItem = 0;
fLastTotal = 0;
fNoOfChunks = 0;
fNoOfItems = 0;
fTotal = 0;
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVOpen
pascal void TRunArray::IRunArray(void)
{
this->IObject();
fChunks = (ChunkArrayHandle)(NewPermHandle(0));
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVClose
pascal void TRunArray::Free(void) // override
{
fChunks = (ChunkArrayHandle)DisposeIfHandle((Handle)fChunks);// Blow chunks
inherited::Free();
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVNonRes
pascal void TRunArray::DeleteItems(short firstItem,
short noOfItems)
{
long offset;
long result;
short i;
short num;
long theTotal;
short index;
if (!FindChunk(firstItem, num, index, theTotal))
{
#if qDebug
Str255 theString;
ConcatNumber("Unable to find chunk for item ", firstItem, theString);
ProgramBreak(theString);
#endif
return;
}
for (i = 1; i <= noOfItems; ++i)
{
fTotal -= (*fChunks)[num].value;
--(*fChunks)[num].count;
if ((*fChunks)[num].count < index)
{
if ((*fChunks)[num].count == 0)
{
// need to delete that chunk
offset = IntMultiply(num, sizeof(RunArrayChunk));
result = Munger((Handle)fChunks, offset, NULL, sizeof(RunArrayChunk), (Ptr) & result, 0);
FailMemError();
--fNoOfChunks;
// Thanks JDR 10/28/89
// see if we can consolidate chunks
if ((num > 0) && (num < fNoOfChunks) && ((*fChunks)[num - 1].value == (*fChunks)[num].value))
{
index = (*fChunks)[num - 1].count + 1;
(*fChunks)[num - 1].count += (*fChunks)[num].count;
// need to delete that chunk
result = Munger((Handle)fChunks, offset, NULL, sizeof(RunArrayChunk), (Ptr) & result, 0);
FailMemError();
--num;
--fNoOfChunks;
}
}
else
++num;
index = 1;
}
}
fNoOfItems -= noOfItems;
// reset the cache
fLastItem = 0;
fLastChunk = 0;
fLastTotal = 0;
fLastIndex = 1;
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVFields
pascal void TRunArray::Fields(TObject* obj) // override
{
Str255 aString;
Str255 numString;
obj->DoToField("TRunArray", NULL, bClass);
obj->DoToField("fNoOfItems", &fNoOfItems, bInteger);
obj->DoToField("fNoOfChunks", &fNoOfChunks, bInteger);
obj->DoToField("fTotal", &fTotal, bLongInt);
obj->DoToField("fLastItem", &fLastItem, bInteger);
obj->DoToField("fLastChunk", &fLastChunk, bInteger);
obj->DoToField("fLastTotal", &fLastTotal, bLongInt);
obj->DoToField("fLastIndex", &fLastIndex, bInteger);
// !!! When these come from the dynamic area remember to put the field in the DynamicField method
for (short i = 0; i <= fNoOfChunks; ++i)
{
NumToString(i, numString);
aString = "count[" + numString + "]";
obj->DoToField(aString, &(*fChunks)[i].count, bInteger);
aString = "value[" + numString + "]";
obj->DoToField(aString, &(*fChunks)[i].value, bInteger);
}
inherited::Fields(obj);
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal Boolean TRunArray::FindChunk(short item,
short& chunk,
short& indexInChunk,
long& theTotal)
{
short thisItem;
short count;
short delta;
Boolean result;
if ((fNoOfChunks <= 0) || (item > fNoOfItems) || (item <= 0))
{
chunk = 0;
theTotal = 0;
indexInChunk = 0;
result = FALSE;
item = 0;
}
else if (item == fLastItem)
{
// check for the very easy case
chunk = fLastChunk;
theTotal = fLastTotal;
indexInChunk = fLastIndex;
result = TRUE;
}
else
{
delta = abs(item - fLastItem);
if ((delta >= item) || (item <= (*fChunks)[0].count))
{
// start from the first chunk
chunk = 0;
theTotal = 0;
thisItem = 0;
}
else if (delta > (fNoOfItems - item + 1))
{
// start from the end chunk
chunk = fNoOfChunks - 1;
count = (*fChunks)[chunk].count;
theTotal = fTotal - IntMultiply(count, (*fChunks)[chunk].value);
thisItem = fNoOfItems - count;
}
else
{ // start from the previous values
chunk = fLastChunk;
theTotal = fLastTotal;
thisItem = fLastItem - fLastIndex;
}
if (item > thisItem)
{
while ((thisItem + (*fChunks)[chunk].count) < item)
{
count = (*fChunks)[chunk].count;
theTotal += IntMultiply(count, (*fChunks)[chunk].value);
thisItem += count;
++chunk;
}
}
else
{
do
{
--chunk;
count = (*fChunks)[chunk].count;
theTotal -= IntMultiply(count, (*fChunks)[chunk].value);
thisItem -= count;
} while (thisItem >= item);
}
indexInChunk = item - thisItem;
result = TRUE;
}
// cache the last values
fLastItem = item;
fLastChunk = chunk;
fLastTotal = theTotal;
fLastIndex = indexInChunk;
return result;
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal short TRunArray::FindItem(long theTotal)
{
short result = 0;
if ((theTotal >= 0) && (theTotal <= fTotal) && (fNoOfChunks > 0))
if (fNoOfChunks == 1)
{
if ((*fChunks)[0].value > 0)
result = (short)Min(((theTotal - 1) / (*fChunks)[0].value) + 1, fNoOfItems);//!!! Cast
}
else if (theTotal == 0)
result = 1;
else
{
++theTotal;
short runningCount = 0;
for (short i = 0; i <= fNoOfChunks - 1; ++i)
{
RunArrayChunk chunk = (*fChunks)[i];
theTotal -= IntMultiply(chunk.value, chunk.count);
runningCount += chunk.count;
if (theTotal <= 0)
{
result = (short)(runningCount + (theTotal / chunk.value));//!!! Cast
return result;
}
}
result = fNoOfItems;
}
return result;
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal short TRunArray::GetValue(short item)
{
short num;
long theTotal;
short index;
if (fNoOfChunks == 1)
return (*fChunks)[0].value;
else if (this->FindChunk(item, num, index, theTotal))
return (*fChunks)[num].value;
else
return 0;
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal void TRunArray::InsertItems(short firstItem,
short noOfItems,
short value)
{
short num;
long theTotal;
short index;
long oldSize;
long result;
struct
{
RunArrayChunk chunk1;
RunArrayChunk chunk2;
} tempChunks;
// Check if we can just increment the last size count
if ((firstItem > fNoOfItems) && (fNoOfChunks > 0) && ((*fChunks)[fNoOfChunks - 1].value == value))
(*fChunks)[fNoOfChunks - 1].count += noOfItems;
// check if we can increment any size count
else if (this->FindChunk(firstItem, num, index, theTotal) && ((*fChunks)[num].value == value))
(*fChunks)[num].count += noOfItems;
// check if this would actually fit as the last item in the previous chunk
// Thanks Martin Frické, 10/31/89
else if ((num > 0) && (index == 1) && ((*fChunks)[num - 1].value == value))
(*fChunks)[num - 1].count += noOfItems;
// We need to create a new chunk, possibly two
else
{
oldSize = GetHandleSize((Handle)fChunks);
tempChunks.chunk1.value = value;
tempChunks.chunk1.count = noOfItems;
if ((index <= 1) || (firstItem > fNoOfItems))
{
// need to add one chunk
if (firstItem > fNoOfItems)
num = fNoOfChunks; // add a row on the end
result = Munger((Handle)fChunks, IntMultiply(num, sizeof(RunArrayChunk)), NULL, 0, (Ptr) & tempChunks, sizeof(RunArrayChunk));
FailMemError();
++fNoOfChunks;
}
else
{
// need to add two
tempChunks.chunk2.count = (*fChunks)[num].count - index + 1;
tempChunks.chunk2.value = (*fChunks)[num].value;
(*fChunks)[num].count = index - 1;
result = Munger((Handle)fChunks, IntMultiply(num + 1, sizeof(RunArrayChunk)), NULL, 0, (Ptr) & tempChunks, 2 * sizeof(RunArrayChunk));
FailMemError();
fNoOfChunks += 2;
}
if (GetHandleSize((Handle)fChunks) <= oldSize)
Failure(memFullErr, 0);
}
// reset the cache
fLastItem = 0;
fLastChunk = 0;
fLastTotal = 0;
fLastIndex = 1;
fNoOfItems += noOfItems;
fTotal += IntMultiply(noOfItems, value);
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal long TRunArray::SumValues(short firstItem,
short noOfItems)
{
short chunk;
short indexInChunk;
long total;
long precedingTotal;
long result;
result = 0;
if (fNoOfChunks == 1)
result = IntMultiply(noOfItems, (*fChunks)[0].value);
else if (firstItem == 1)
{
if (this->FindChunk(noOfItems, chunk, indexInChunk, total))
result = total + IntMultiply(indexInChunk, (*fChunks)[chunk].value);
}
else if (this->FindChunk(firstItem, chunk, indexInChunk, total))
{
precedingTotal = total + IntMultiply(indexInChunk - 1, (*fChunks)[chunk].value);
if (this->FindChunk(firstItem + noOfItems - 1, chunk, indexInChunk, total))
result = total + IntMultiply(indexInChunk, (*fChunks)[chunk].value) - precedingTotal;
}
return result;
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVOpen
pascal void TGridView::Initialize(void) // override
{
inherited::Initialize();
#if qDebug
if (!gUGridViewInitialized)
{
ProgramBreak("InitUGridView must be called before creating a grid view.");
Failure(noErr, 0);
}
#endif
fNumOfRows = 0;
fNumOfCols = 0;
fAdornRows = FALSE;
fAdornCols = FALSE;
fRowInset = 0;
fColInset = 0;
fColWidths = NULL;
fRowHeights = NULL;
fSelections = NULL;
fHLRegion = NULL;
fTempSelections = NULL;
fSingleSelection = TRUE;
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVOpen
pascal void TGridView::IGridView(TDocument* itsDocument,
// Its document
TView* itsSuperView,
// Its parent view
const VPoint& itsLocation,
// Top, Left in parent's coords
const VPoint& itsSize,
// Ignored for SizeVariable
SizeDeterminer itsHSizeDet,
SizeDeterminer itsVSizeDet,
// Size determiners
short numOfRows,
// Number of rows initially
short numOfCols,
// Number of columns initially
short rowHeight,
// Height of initial rows
short colWidth,
// Height of initial columns
Boolean adornRows,
// Adornment for Rows?
Boolean adornCols,
// Adornment for Columns?
short rowInset,
// horizontal space between cells
short colInset,
// vertical space between cells
Boolean singleSelection)// single cell selection?
{
FailInfo fi;
fSelections = NULL;
fHLRegion = NULL;
fTempSelections = NULL;
fColWidths = NULL;
fRowHeights = NULL;
#if qDebug
if (!gUGridViewInitialized)
{
ProgramBreak("InitUGridView must be called before creating a grid view.");
Failure(noErr, 0);
}
#endif
this->IView(itsDocument, itsSuperView, itsLocation, itsSize, itsHSizeDet, itsVSizeDet);
fAdornRows = adornRows;
fAdornCols = adornCols;
// Make sure the insets are evenly divided between top/bottom or left/right
if (rowInset & 1) // (ODD(rowInset))
fRowInset = rowInset + 1;
else
fRowInset = rowInset;
if (colInset & 1) // (ODD(colInset))
fColInset = colInset + 1;
else
fColInset = colInset;
if (fi.Try())
{
fColWidths = new TRunArray;
fColWidths->IRunArray();
fRowHeights = new TRunArray;
fRowHeights->IRunArray();
fSelections = MakeNewRgn(); // region to hold current selections
fHLRegion = MakeNewRgn(); // region to hold current highlighted cells
fTempSelections = MakeNewRgn(); // used by SetSelectionRect
fSingleSelection = singleSelection;
if (numOfCols > 0)
this->InsColFirst(numOfCols, colWidth);
if (numOfRows > 0)
this->InsRowFirst(numOfRows, rowHeight);
fi.Success();
}
else // Recover
{
this->Free();
fi.ReSignal();
}
this->AddAdorner(gSelectionAdorner, kViewAdornPriority, FALSE); // wants DoHighlightSelection
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVOpen
pascal void TGridView::IRes(TDocument* itsDocument,
TView* itsSuperView,
Ptr& itsParams) // override
{
FailInfo fi;
fSelections = NULL;
fHLRegion = NULL;
fTempSelections = NULL;
fColWidths = NULL;
fRowHeights = NULL;
#if qDebug
if (!gUGridViewInitialized)
{
ProgramBreak("InitUGridView must be called before creating a grid view.");
Failure(noErr, 0);
}
#endif
inherited::IRes(itsDocument, itsSuperView, itsParams);
GridViewTemplate& templateData = *((GridViewTemplate *) itsParams);
fNumOfRows = 0;
fNumOfCols = 0;
fAdornRows = templateData.adornRows;
fAdornCols = templateData.adornCols;
// Make sure the insets are evenly divided between top/bottom or left/right
if (templateData.rowInset & 1) // (ODD(templateData.rowInset))
fRowInset = templateData.rowInset + 1;
else
fRowInset = templateData.rowInset;
if (templateData.colInset & 1) // (ODD(templateData.colInset))
fColInset = templateData.colInset + 1;
else
fColInset = templateData.colInset;
fSingleSelection = templateData.singleSelection;
if (fi.Try())
{
fColWidths = new TRunArray;
fColWidths->IRunArray();
fRowHeights = new TRunArray;
fRowHeights->IRunArray();
fSelections = MakeNewRgn(); // region to hold current selections
fHLRegion = MakeNewRgn(); // region to hold current highlighted cells
fTempSelections = MakeNewRgn(); // used by SetSelectionRect
if (templateData.numOfCols > 0)
this->InsColFirst(templateData.numOfCols, templateData.colWidth);
if (templateData.numOfRows > 0)
this->InsRowFirst(templateData.numOfRows, templateData.rowHeight);
fi.Success();
}
else // Recover
{
this->Free();
fi.ReSignal();
}
OffsetPtr(itsParams, sizeof(GridViewTemplate));
this->AddAdorner(gSelectionAdorner, kViewAdornPriority, FALSE); // wants DoHighlightSelection
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal TObject* TGridView::Clone(void) // override
{
TGridView * aClonedGridView;
FailInfo fi;
VOLATILE(aClonedGridView);
aClonedGridView = (TGridView *)(inherited::Clone());
aClonedGridView->fNumOfCols = 0;
aClonedGridView->fNumOfRows = 0;
// This code is neccessary becuase MacApp does not support cloning properly
// It could be replaced with TGridView(inputView).fColWidths.Clone otherwise
if (fi.Try())
{
aClonedGridView->fColWidths = new TRunArray;
aClonedGridView->fColWidths->IRunArray();
aClonedGridView->fRowHeights = new TRunArray;
aClonedGridView->fRowHeights->IRunArray();
aClonedGridView->fSelections = MakeNewRgn();// region to hold current selections
aClonedGridView->fHLRegion = MakeNewRgn();// region to hold current highlighted cells
aClonedGridView->fTempSelections = MakeNewRgn();// used by SetSelectionRect
fi.Success();
}
else // Recover
{
aClonedGridView->Free();
fi.ReSignal();
}
if (fNumOfCols > 0)
aClonedGridView->InsColFirst(fNumOfCols, this->GetColWidth(1));
if (fNumOfRows > 0)
aClonedGridView->InsRowFirst(fNumOfRows, this->GetRowHeight(1));
return aClonedGridView;
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVNonRes
pascal void TGridView::WRes(ViewRsrcHandle theResource,
Ptr& itsParams) // override
{
inherited::WRes(theResource, itsParams);
GridViewTemplate& templateData = *((GridViewTemplate *) ExpandPtr((Handle)theResource, itsParams, sizeof(GridViewTemplate)));
templateData.numOfRows = fNumOfRows;
templateData.numOfCols = fNumOfCols;
if (fNumOfRows > 0)
templateData.rowHeight = this->GetRowHeight(1);
else
templateData.rowHeight = 0;
if (fNumOfCols > 0)
templateData.colWidth = this->GetColWidth(1);
else
templateData.colWidth = 0;
templateData.rowInset = fRowInset;
templateData.colInset = fColInset;
templateData.adornRows = fAdornRows;
templateData.adornCols = fAdornCols;
templateData.singleSelection = fSingleSelection;
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVNonRes
pascal void TGridView::WriteRes(ViewRsrcHandle theResource,
Ptr& itsParams) // override
{
gWResSignature = 'grid';
gWResType = "TGridView";
this->WRes(theResource, itsParams);
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVClose
pascal void TGridView::Free(void) // override
{
// Dispose regions
fSelections = DisposeIfRgnHandle(fSelections);
fHLRegion = DisposeIfRgnHandle(fHLRegion);
fTempSelections = DisposeIfRgnHandle(fTempSelections);
fColWidths = (TRunArray *)(FreeIfObject(fColWidths));
fRowHeights = (TRunArray *)(FreeIfObject(fRowHeights));
inherited::Free();
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal void TGridView::AllCellsDo(DoToCellType DoToCell,
void* staticLink)
{
Rect bounds(1, 1, fNumOfRows, fNumOfCols);
this->EachCellDo(bounds[topLeft], bounds[botRight], DoToCell, staticLink);
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal void TGridView::AdornCol(short aCol,
const VRect& area)
{
Rect qdRect;
PenNormal();
this->ViewToQDRect(area, qdRect);
MoveTo(qdRect.right, qdRect.top);
Line(0, qdRect.Length(vSel));
if (aCol == 1)
{
MoveTo(qdRect.left, qdRect.top);
Line(0, qdRect.Length(vSel));
}
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal void TGridView::AdornRow(short aRow,
const VRect& area)
{
Rect qdRect;
PenNormal();
this->ViewToQDRect(area, qdRect);
MoveTo(qdRect.left, qdRect.bottom);
Line(qdRect.Length(hSel), 0);
if (aRow == 1)
{
MoveTo(qdRect.left, qdRect.top);
Line(qdRect.Length(hSel), 0);
}
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal void TGridView::CalcMinSize(VPoint& minSize)// override
{
inherited::CalcMinSize(minSize);
// Set the amount of room needed for that many items
minSize = VPoint(fRowHeights->fTotal, fColWidths->fTotal);
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal Boolean TGridView::CanSelectCell(GridCell aCell)
{
return ((aCell.h >= 1) && (aCell.v >= 1) && (aCell.h <= fNumOfCols) && (aCell.v <= fNumOfRows));
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal void TGridView::CellToVRect(GridCell aCell,
VRect& aRect)
{
short width;
short height;
if ((aCell.h < 1) || (aCell.v < 1) || (aCell.h > fNumOfCols) || (aCell.v > fNumOfRows))
{
#if qRangeCheck && qDebugMsg
fprintf(stderr, "aCell.h == %6d fNumOfCols == %6d", aCell.h, fNumOfCols);
fprintf(stderr, "aCell.v == %6d fNumOfCols == %6d", aCell.v, fNumOfCols);
ProgramBreak("Range Check in CellToVRect");
#endif
aRect = gZeroVRect;
}
else // all the params look OK
{
width = fColWidths->GetValue(aCell.h);
if (fColWidths->fNoOfChunks == 1)
aRect.left = IntMultiply(width, aCell.h - 1);
else
aRect.left = fColWidths->SumValues(1, aCell.h - 1);
aRect.right = aRect.left + width;
height = fRowHeights->GetValue(aCell.v);
if (fRowHeights->fNoOfChunks == 1)
aRect.top = IntMultiply(height, aCell.v - 1);
else
aRect.top = fRowHeights->SumValues(1, aCell.v - 1);
aRect.bottom = aRect.top + height;
}
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal void TGridView::ColToVRect(short aCol,
short numOfCols,
VRect& aRect)
{
long width;
long leftEdge;
if ((aCol < 1) || (numOfCols < 1) || (aCol + numOfCols - 1 > fNumOfCols))
{
#if qDebugMsg && qRangeCheck
fprintf(stderr, "fNumOfCols == %1d aCol == %1d", fNumOfCols, aCol);
ProgramBreak("Range Check in ColToVRect");
#endif
aRect = gZeroVRect;
}
else // all the params look OK
{
if (fColWidths->fNoOfChunks == 1) // only one column height
{
width = this->GetColWidth(1);
leftEdge = IntMultiply((short)width, aCol - 1);//!!! cast
width = IntMultiply((short)width, numOfCols);//!!! cast
}
else
{
leftEdge = fColWidths->SumValues(1, aCol - 1);
width = fColWidths->SumValues(aCol, numOfCols);
}
aRect = VRect(0, leftEdge, fRowHeights->fTotal, leftEdge + width);
}
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal void TGridView::AddStrip(RgnHandle thePixels,
VHSelect direction,
short& startOfStrip,
short endOfStrip,
Rect& stripRect,
short row,
short col,
VRect& pixels,
VRect& prevPixels,
Rect& prevstripRect)
{
Rect qdRect;
if (direction == vSel)
stripRect = Rect(startOfStrip, col, endOfStrip, col);
else
stripRect = Rect(row, startOfStrip, row, endOfStrip);
#if qDebugMsg
if (gIntenseDebugging)
{
WrLblRect("Adding cells", stripRect);
fprintf(stderr, "\n");
}
#endif
pixels = prevPixels;
if (stripRect.top != prevstripRect.top)
pixels.top = this->fRowHeights->SumValues(1, stripRect.top - 1);
if (stripRect.bottom != prevstripRect.bottom)
{
if (stripRect.bottom == stripRect.top)
pixels.bottom = pixels.top + this->fRowHeights->GetValue(stripRect.bottom);
else
pixels.bottom = this->fRowHeights->SumValues(1, stripRect.bottom);
}
if (stripRect.left != prevstripRect.left)
pixels.left = this->fColWidths->SumValues(1, stripRect.left - 1);
if (stripRect.right != prevstripRect.right)
{
if (stripRect.right == stripRect.left)
pixels.right = pixels.left + this->fColWidths->GetValue(stripRect.right);
else
pixels.right = this->fColWidths->SumValues(1, stripRect.right);
}
prevPixels = pixels;
#if qDebug
UseTempRgn("TGridView::AddStrip()");
#endif
SetEmptyRgn(gTempRgn);
this->ViewToQDRect(pixels, qdRect);
RectRgn(gTempRgn, qdRect);
UnionRgn(gTempRgn, thePixels, thePixels);
#if qDebug
DoneWithTempRgn();
#endif
prevstripRect = stripRect;
startOfStrip = 0;
}
pascal void TGridView::CellsToPixels(RgnHandle theCells,
RgnHandle thePixels)
{
Rect cellBounds;
VRect visibleVRect;
Rect visibleCells;
Rect stripRect;
GridCell aCell;
short row,
col;
VRect pixels;
VRect prevPixels;
Rect prevstripRect;
VHSelect direction;
short startOfStrip;
SetEmptyRgn(thePixels);
if (!EmptyRgn(theCells) && this->Focus())
if ((*theCells)->rgnSize == 10) // the region is a rectangle
{
cellBounds = (**theCells).rgnBBox;
pixels = VRect(fRowHeights->SumValues(1, cellBounds.top - 1), fColWidths->SumValues(1, cellBounds.left - 1),
fRowHeights->SumValues(1, cellBounds.bottom - 1), fColWidths->SumValues(1, cellBounds.right - 1));
this->ViewToQDRect(pixels, (**thePixels).rgnBBox);
}
else
{
// Reduce the cells to only those that are visible
this->GetVisibleRect(visibleVRect);
// !!!FIX the following 2 lines after MPW C compiler bug is corrected.
GridCell temp = this->VPointToLastCell(visibleVRect[topLeft]);
visibleCells[topLeft] = temp;
// !!!FIX the following 2 lines after MPW C compiler bug is corrected.
temp = this->VPointToLastCell(visibleVRect[botRight]);
visibleCells[botRight] = temp;
SetRectRgn(pVisibleCells, visibleCells.left, visibleCells.top, visibleCells.right + 1, visibleCells.bottom + 1);
SectRgn(theCells, pVisibleCells, pVisibleCells);
cellBounds = (**pVisibleCells).rgnBBox;
prevstripRect = gZeroRect;
direction = LongerSide(cellBounds);
if (direction == vSel)
for (col = cellBounds.left; col < cellBounds.right; ++col)
{
aCell.h = col;
startOfStrip = 0;
for (row = cellBounds.top; row < cellBounds.bottom; ++row)
{
aCell.v = row;
if (PtInRgn(aCell, pVisibleCells))
{
if (startOfStrip == 0)
startOfStrip = row;
}
else if (startOfStrip > 0)
this->AddStrip(thePixels, direction, startOfStrip, row - 1, stripRect, row, col, pixels, prevPixels, prevstripRect);
}
if (startOfStrip > 0)
this->AddStrip(thePixels, direction, startOfStrip, cellBounds.bottom - 1, stripRect, row, col, pixels, prevPixels, prevstripRect);
}
else
for (row = cellBounds.top; row < cellBounds.bottom; ++row)
{
aCell.v = row;
startOfStrip = 0;
for (col = cellBounds.left; col < cellBounds.right; ++col)
{
aCell.h = col;
if (PtInRgn(aCell, pVisibleCells))
{
if (startOfStrip == 0)
startOfStrip = col;
}
else if (startOfStrip > 0)
this->AddStrip(thePixels, direction, startOfStrip, col - 1, stripRect, row, col, pixels, prevPixels, prevstripRect);
}
if (startOfStrip > 0)
this->AddStrip(thePixels, direction, startOfStrip, cellBounds.right - 1, stripRect, row, col, pixels, prevPixels, prevstripRect);
}
}
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal void TGridView::DoHighlightSelection(HLState fromHL,
HLState toHL)// override
{
if (!EmptyRgn(fHLRegion))
this->HighlightCells(fHLRegion, fromHL, toHL);
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal void TGridView::HighlightCells(RgnHandle theCells,
HLState fromHL,
HLState toHL)
{
if (fromHL == hlDim) // GridViews don't support dim highlighting
fromHL = hlOff;
if (toHL == hlDim)
toHL = hlOff;
if ((fromHL != toHL) && this->Focus())
{
this->CellsToPixels(theCells, pPixelsToHighlight);
PenNormal();
UseSelectionColor();
InvertRgn(pPixelsToHighlight); // highlight the cells
}
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal void TGridView::DoMouseCommand(VPoint& theMouse,
TToolboxEvent* event,
Point) // override
{
short aRow;
short aCol;
if (this->IdentifyPoint(theMouse, aRow, aCol) != badChoice)
{
TCellSelectCommand * aCellSelectCommand = new TCellSelectCommand;
aCellSelectCommand->ICellSelectCommand(this, theMouse, event->fShiftKey, event->fCmdKey);
this->PostCommand(aCellSelectCommand);
}
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal void TGridView::Draw(const VRect& area) // override
{
VRect aRect;
VRect bRect;
register short i;
GridCell startCell;
GridCell stopCell;
VRect viewArea;
GridCell startCellToDraw;
VRect cellsArea;
VRect localArea(area); // use localArea (because area is const)
if ((fNumOfRows > 0) && (fNumOfCols > 0))
{
// make sure we have something to draw
viewArea = localArea;
startCell = this->VPointToLastCell(viewArea[topLeft]);
stopCell = this->VPointToLastCell(viewArea[botRight]);
this->CellToVRect(startCell, aRect);
this->CellToVRect(stopCell, bRect);
bRect[topLeft] = aRect[topLeft];
localArea = bRect;
startCellToDraw = startCell;
cellsArea = localArea;
if (viewArea.top >= aRect.bottom - (fRowInset / 2)) //((fRowInset) >> 1)
{
++startCellToDraw.v;
cellsArea.top += aRect.Length(vSel);
}
this->DrawRangeOfCells(startCellToDraw, stopCell, cellsArea);
if (fAdornCols)
{
short colWidth = 0;
aRect = localArea;
register Boolean constantWidth = fColWidths->fNoOfChunks == 1;
if (constantWidth) // only one width
colWidth = this->GetColWidth(1);
for (i = startCell.h; i <= stopCell.h; ++i)
{
if (constantWidth)
aRect.right = aRect.left + colWidth;
else
aRect.right = aRect.left + this->GetColWidth(i);
this->AdornCol(i, aRect);
aRect.left = aRect.right;
}
}
if (fAdornRows)
{
short rowHeight = 0;
aRect = localArea;
register Boolean constantHeight = fRowHeights->fNoOfChunks == 1;
if (constantHeight) // only one height
rowHeight = this->GetRowHeight(1);
for (i = startCell.v; i <= stopCell.v; ++i)
{
if (constantHeight)
aRect.bottom = aRect.top + rowHeight;
else
aRect.bottom = aRect.top + this->GetRowHeight(i);
this->AdornRow(i, aRect);
aRect.top = aRect.bottom;
}
}
}
inherited::Draw(localArea);
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal void TGridView::DrawRangeOfCells(GridCell startCell,
GridCell stopCell,
const VRect& aRect)
{
VCoordinate colWidth;
VCoordinate rowHeight;
short i,
j;
GridCell aCell;
VCoordinate left;
VRect localVRect; //!!! added because argument is const
localVRect = aRect; //!!! added because argument is const
localVRect.left += fColInset / 2;
localVRect.top += fRowInset / 2;
left = localVRect.left;
if (fColWidths->fNoOfChunks == 1) // only one width
colWidth = this->GetColWidth(1);
if (fRowHeights->fNoOfChunks == 1) // only one height
rowHeight = this->GetRowHeight(1);
for (j = startCell.v; j <= stopCell.v; ++j)
{
if (fRowHeights->fNoOfChunks == 1) // only one height
localVRect.bottom = localVRect.top + rowHeight - fRowInset;
else
localVRect.bottom = localVRect.top + this->GetRowHeight(j) - fRowInset;
localVRect.left = left; // start back at the left for the next row
for (i = startCell.h; i <= stopCell.h; ++i)
{
if (fColWidths->fNoOfChunks == 1) // only one height
localVRect.right = localVRect.left + colWidth - fColInset;
else
localVRect.right = localVRect.left + this->GetColWidth(i) - fColInset;
aCell.h = i;
aCell.v = j;
this->DrawCell(aCell, localVRect);
localVRect.left = localVRect.right + fColInset;
}
localVRect.top = localVRect.bottom + fRowInset;
}
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal void TGridView::DrawCell(GridCell /* aCell */,
const VRect& /* aRect */)
{
this->SubClassResponsibility();
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVNonRes
pascal void TGridView::DelColAt(short aCol,
short numOfCols)
{
VRect aRect;
if ((aCol < 1) || (numOfCols < 1) || (aCol + numOfCols - 1 > fNumOfCols))
{
if (numOfCols != 0)
{
#if qDebugMsg
fprintf(stderr, "fNumOfCols == %1d aCol == %1d\n", fNumOfCols, aCol);
ProgramBreak("Range Check in DelColAt");
return;
#endif
}
}
else
{
this->ColToVRect((short)Max(1, aCol), (short)Max(1, fNumOfCols - aCol + 1), aRect);//!!! cast
fColWidths->DeleteItems(aCol, numOfCols);
fNumOfCols = fNumOfCols - numOfCols;
this->AdjustSize();
this->InvalidateVRect(aRect);
}
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVNonRes
pascal void TGridView::DelRowAt(short aRow,
short numOfRows)
{
VRect aRect;
if ((aRow < 1) || (numOfRows < 1) || (aRow + numOfRows - 1 > fNumOfRows))
{
if (numOfRows != 0)
{
#if qDebugMsg
fprintf(stderr, "fNumOfRows == %1d aRow == %1d\n", fNumOfRows, aRow);
ProgramBreak("Range Check in DelRowAt");
return;
#endif
}
}
else
{
this->RowToVRect((short)Max(1, aRow), (short)Max(1, fNumOfRows - aRow + 1), aRect);//!!! cast
fRowHeights->DeleteItems(aRow, numOfRows);
fNumOfRows = fNumOfRows - numOfRows;
this->AdjustSize();
this->InvalidateVRect(aRect);
}
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVNonRes
pascal void TGridView::DelColFirst(short numOfCols)
{
this->DelColAt(1, numOfCols);
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVNonRes
pascal void TGridView::DelRowFirst(short numOfRows)
{
this->DelRowAt(1, numOfRows);
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVNonRes
pascal void TGridView::DelColLast(short numOfCols)
{
this->DelColAt(fNumOfCols - numOfCols + 1, numOfCols);
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVNonRes
pascal void TGridView::DelRowLast(short numOfRows)
{
this->DelRowAt(fNumOfRows - numOfRows + 1, numOfRows);
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal void TGridView::EachCellDo(GridCell startCell,
GridCell stopCell,
pascal void(* DoToCell)(GridCell aCell,
void* staticLink),
void* staticLink)
{
short i,
j;
short firstRow;
short lastRow;
short firstCol;
short lastCol;
GridCell aCell;
firstRow = (short)Max(1, startCell.v); //!!! Cast
firstCol = (short)Max(1, startCell.h); //!!! Cast
lastRow = (short)Min(fNumOfRows, stopCell.v);//!!! Cast
lastCol = (short)Min(fNumOfCols, stopCell.h);//!!! Cast
for (j = firstRow; j <= lastRow; ++j)
{
aCell.v = j;
for (i = firstCol; i <= lastCol; ++i)
{
aCell.h = i;
DoToCell(aCell, staticLink);
}
}
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal void TGridView::EachColDo(short startCol,
short stopCol,
pascal void(* DoToCol)(short aCol,
void* staticLink),
void* staticLink)
{
short firstCol;
short lastCol;
firstCol = (short)Max(1, startCol); //!!! Cast
lastCol = (short)Min(fNumOfCols, stopCol); //!!! Cast
for (short i = firstCol; i <= lastCol; ++i)
DoToCol(i, staticLink);
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal void TGridView::EachRowDo(short startRow,
short stopRow,
pascal void(* DoToRow)(short aRow,
void* staticLink),
void* staticLink)
{
short firstRow;
short lastRow;
firstRow = (short)Max(1, startRow); //!!! Cast
lastRow = (short)Min(fNumOfRows, stopRow); //!!! Cast
for (short i = firstRow; i <= lastRow; ++i)
DoToRow(i, staticLink);
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal void TGridView::EachSelectedCellDo(pascal void(* DoToCell)(GridCell aCell,
void* staticLink),
void* staticLink)
{
this->EachInRgn(fSelections, DoToCell, staticLink);
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal void TGridView::EachInRgn(RgnHandle aRgn,
pascal void(* DoToCell)(GridCell aCell,
void* staticLink),
void* staticLink)
{
GridCell aCell;
Rect boundsRect;
boundsRect = (*aRgn)->rgnBBox;
--boundsRect.right;
--boundsRect.bottom;
if ((**aRgn).rgnSize == 10) // its a rectangle
this->EachCellDo(boundsRect[topLeft], boundsRect[botRight], DoToCell, staticLink);
else
for (short row = boundsRect.top; row <= boundsRect.bottom; ++row)
{
aCell.v = row;
for (short col = boundsRect.left; col <= boundsRect.right; ++col)
{
aCell.h = col;
if (PtInRgn(aCell, aRgn))
DoToCell(aCell, staticLink);
}
}
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal GridCell TGridView::FirstSelectedCell(void)
{
Rect bounds;
GridCell aCell;
GridCell result;
result = gZeroPt;
if (this->IsAnyCellSelected())
{
bounds = (*fSelections)->rgnBBox;
if ((**fSelections).rgnSize == 10) // whole rectangle
result = bounds[topLeft];
else
for (short i = bounds.top; i <= bounds.bottom - 1; ++i)
{
aCell.v = i;
for (short j = bounds.left; j <= bounds.right - 1; ++j)
{
aCell.h = j;
if (PtInRgn(aCell, fSelections))
{
result = aCell;
return result;
}
}
}
}
return result;
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal short TGridView::GetColWidth(short aCol)
{
if ((aCol < 1) || (aCol > fNumOfCols))
{
#if qRangeCheck && qDebugMsg
fprintf(stderr, "fNumOfCols == &1d aCol == %1d\n", fNumOfCols, aCol);
ProgramBreak("Range Check in GetColWidth");
#endif
return 0;
}
else
return fColWidths->GetValue(aCol);
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal short TGridView::GetRowHeight(short aRow)
{
if ((aRow < 1) || (aRow > fNumOfRows))
{
#if qRangeCheck && qDebugMsg
fprintf(stderr, "fNumOfRows == &1d aRow == %1d\n", fNumOfRows, aRow);
ProgramBreak("Range Check in GetRowHeight");
#endif
return 0;
}
else
return fRowHeights->GetValue(aRow);
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal void TGridView::InvalidateCell(GridCell aCell)
{
VRect aRect;
this->CellToVRect(aCell, aRect);
this->InvalidateVRect(aRect);
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal void TGridView::InvalidateSelection(void)
{
if (this->Focus())
{
this->CellsToPixels(fSelections, pInvalidateRgn);
this->InvalidateRgn(pInvalidateRgn);
}
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal GridViewPart TGridView::IdentifyPoint(const VPoint& thePoint,
short& aRow,
short& aCol)
{
VRect aRect;
GridCell aCell;
GridViewPart aGridViewPart;
aCell = this->VPointToCell(thePoint);
aRow = aCell.v;
aCol = aCell.h;
if (aCell == gZeroPt)
aGridViewPart = badChoice;
else
{
this->CellToVRect(aCell, aRect);
aRect.Inset(VPoint(fRowInset / 2, fColInset / 2));
aGridViewPart = inCell;
if (fColInset > 0)
{
if (thePoint.h < aRect.left)
{
aGridViewPart = inColumn; // To the left of the cell
}
else if (thePoint.h >= aRect.right) /* Remember PtInRgn will report a point as in
a region only if the pixel to the right
and below the point is contained in the
region. */
{
aGridViewPart = inColumn; // To the right of the cell
++aCol;
}
}
if (fRowInset > 0)
{
if (thePoint.v < aRect.top)
{
if (aGridViewPart == inColumn)
aGridViewPart = inVertex; // Click on both
else
aGridViewPart = inRow; // Above the cell
}
else if (thePoint.v >= aRect.bottom)/* Remember PtInRgn will report a point as in
a region only if the pixel to the right
and below the point is contained in the
region. */
{
if (aGridViewPart == inColumn)
aGridViewPart = inVertex; // Click on both
else
aGridViewPart = inRow; // Above the cell
++aRow;
}
}
}
return aGridViewPart;
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal void TGridView::InsColBefore(short aCol,
short numOfCols,
short aWidth)
{
VRect aRect;
if ((aCol < 1) || (numOfCols < 1))
{
if (numOfCols != 0)
{
#if qDebugMsg && qRangeCheck
fprintf(stderr, "fNumOfCols == %1d aCol == %1d", fNumOfCols, aCol);
ProgramBreak("Range Check in InsColBefore");
#endif
}
}
else
{
fColWidths->InsertItems(aCol, numOfCols, aWidth);
fNumOfCols += numOfCols;
this->AdjustSize();
this->ColToVRect((short)Max(1, aCol), (short)Max(1, fNumOfCols - aCol + 1), aRect);//!!! Cast
this->InvalidateVRect(aRect);
}
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal void TGridView::InsRowBefore(short aRow,
short numOfRows,
short aHeight)
{
VRect aRect;
if ((aRow < 1) || (numOfRows < 1))
{
if (numOfRows != 0)
{
#if qDebugMsg && qRangeCheck
fprintf(stderr, "fNumOfRows == %1d aRow == %1d", fNumOfRows, aRow);
ProgramBreak("Range Check in InsRowBefore");
#endif
}
}
else
{
fRowHeights->InsertItems(aRow, numOfRows, aHeight);
fNumOfRows = fNumOfRows + numOfRows;
this->AdjustSize();
this->RowToVRect((short)Max(1, aRow), (short)Max(1, fNumOfRows - aRow + 1), aRect);//!!! Cast
this->InvalidateVRect(aRect);
}
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal void TGridView::InsColLast(short numOfCols,
short aWidth)
{
this->InsColBefore(fNumOfCols + 1, numOfCols, aWidth);
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal void TGridView::InsRowLast(short numOfRows,
short aHeight)
{
this->InsRowBefore(fNumOfRows + 1, numOfRows, aHeight);
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal void TGridView::InsColFirst(short numOfCols,
short aWidth)
{
this->InsColBefore(1, numOfCols, aWidth);
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal void TGridView::InsRowFirst(short numOfRows,
short aHeight)
{
this->InsRowBefore(1, numOfRows, aHeight);
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal Boolean TGridView::IsCellSelected(GridCell aCell)
{
return PtInRgn(aCell, fSelections);
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal Boolean TGridView::IsAnyCellSelected(void)
{
return !EmptyRgn(fSelections);
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal GridCell TGridView::LastSelectedCell(void)
{
Rect bounds;
GridCell aCell;
GridCell result;
result = gZeroPt;
if (this->IsAnyCellSelected())
{
bounds = (**fSelections).rgnBBox;
if ((**fSelections).rgnSize == 10) // whole rectangle
{
aCell.h = bounds.right - 1;
aCell.v = bounds.bottom - 1;
result = aCell;
}
else
for (short i = bounds.bottom - 1; i >= bounds.top; i--)
{
aCell.v = i;
for (short j = bounds.right - 1; j >= bounds.left; j--)
{
aCell.h = j;
if (PtInRgn(aCell, fSelections))
{
result = aCell;
return result;
}
}
}
}
return result;
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal void TGridView::RowToVRect(short aRow,
short numOfRows,
VRect& aRect)
{
long height;
long topEdge;
if ((aRow < 1) || (numOfRows < 1) || (aRow + numOfRows - 1 > fNumOfRows))
{
#if qDebugMsg && qRangeCheck
fprintf(stderr, "fNumOfRows == %1d aRow == %1d", fNumOfRows, aRow);
ProgramBreak("Range Check in RowToVRect");
#endif
aRect = gZeroVRect;
}
else // all the params look OK
{
if (fRowHeights->fNoOfChunks == 1) // only one row height
{
height = fRowHeights->GetValue(1);
topEdge = IntMultiply((short)height, aRow - 1);//!!! Cast
height = IntMultiply((short)height, numOfRows);//!!! Cast
}
else
{
topEdge = fRowHeights->SumValues(1, aRow - 1);
height = fRowHeights->SumValues(aRow, numOfRows);
}
aRect = VRect(topEdge, 0, topEdge + height, fColWidths->fTotal);
}
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal void TGridView::ScrollSelectionIntoView(Boolean redraw)
{
VRect topLeftRect;
VRect botRightRect;
VRect selectionRect;
if (this->IsAnyCellSelected())
{
this->CellToVRect((**fSelections).rgnBBox[topLeft], topLeftRect);
GridCell botRightCell((**fSelections).rgnBBox.bottom - 1, (**fSelections).rgnBBox.right - 1);
this->CellToVRect(botRightCell, botRightRect);
selectionRect = topLeftRect | botRightRect;
VPoint minToSee(Max(topLeftRect.Length(vSel), botRightRect.Length(vSel)),
Max(topLeftRect.Length(hSel), botRightRect.Length(hSel)));
this->RevealRect(selectionRect, minToSee, redraw);
}
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVNonRes
pascal void TGridView::SetColWidth(short aCol,
short numOfCols,
short aWidth)
{
VRect aRect;
#if qDebugMsg
if ((aCol < 1) || (numOfCols < 1) || (aCol + numOfCols - 1 > fNumOfCols))
{
fprintf(stderr, "fNumOfCols == %1d aCol == %1d", fNumOfCols, aCol);
ProgramBreak("Range Check in SetColWidth");
return;
}
#endif
if ((fColWidths->fNoOfChunks > 1) || (this->GetColWidth(1) != aWidth))
{
fColWidths->DeleteItems(aCol, numOfCols);
fColWidths->InsertItems(aCol, numOfCols, aWidth);
this->AdjustSize();
this->ColToVRect((short)Max(1, aCol), (short)Max(1, fNumOfCols - aCol + 1), aRect);//!!! Cast
this->InvalidateVRect(aRect);
}
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVNonRes
pascal void TGridView::SetRowHeight(short aRow,
short numOfRows,
short aHeight)
{
VRect aRect;
#if qDebugMsg
if ((aRow < 1) || (numOfRows < 1) || (aRow + numOfRows - 1 > fNumOfRows))
{
fprintf(stderr, "fNumOfRows == %1d aRow == %1d", fNumOfRows, aRow);
ProgramBreak("Range Check in SetRowHeight.");
return;
}
#endif
if (!((fRowHeights->fNoOfChunks == 1) && (this->GetRowHeight(1) == aHeight)))
{
fRowHeights->DeleteItems(aRow, numOfRows);
fRowHeights->InsertItems(aRow, numOfRows, aHeight);
this->AdjustSize();
this->RowToVRect((short)Max(1, aRow), (short)Max(1, fNumOfRows - aRow + 1), aRect);//!!! Cast
this->InvalidateVRect(aRect);
}
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal void TGridView::SelectCell(GridCell theCell,
Boolean extendSelection,
Boolean highlight,
Boolean select)
{
this->SetSelectionRect(theCell.h, theCell.v, theCell.h, theCell.v, extendSelection, highlight, select);
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal void TGridView::SetEmptySelection(Boolean highlight)
{
SetEmptyRgn(fTempSelections);
this->SetSelection(fTempSelections, kDontExtend, highlight, kSelect);
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal void TGridView::SetSelection(RgnHandle cellsToSelect,
Boolean extendSelection,
Boolean highlight,
Boolean select)
{
#if qDebug
Rect & bounds = (**cellsToSelect).rgnBBox;
if (fSingleSelection && ((bounds.Length(hSel) > 1) || (bounds.Length(vSel) > 1)))
ProgramBreak("Attempt to select multiple cells when fSingleSelection is true");
if (!EmptyRgn(cellsToSelect))
if ((bounds.left < 1) || (bounds.top < 1) || (bounds.right > fNumOfCols + 1) || (bounds.bottom > fNumOfRows + 1))
ProgramBreak("Attempted selection is outside the range of cells");
#endif
if (highlight)
CopyRgn(fSelections, pPreviousSelection);// save the old selection
#if qDebug
UseTempRgn("TGridView.SetSelection");
#endif
SetRectRgn(gTempRgn, 1, 1, fNumOfCols + 1, fNumOfRows + 1);
SectRgn(cellsToSelect, gTempRgn, gTempRgn);
if (extendSelection && select) // extend the selection region
UnionRgn(gTempRgn, fSelections, fSelections);
else if (select) // reset the selection region
CopyRgn(gTempRgn, fSelections);
else // need to de-select the new region
DiffRgn(fSelections, gTempRgn, fSelections);
#if qDebug
DoneWithTempRgn();
#endif
this->UserSelectionChanged(); // so doc updates its designator
CopyRgn(fSelections, fHLRegion);
if (highlight)
{
// Turn the deselected cells off
DiffRgn(pPreviousSelection, fSelections, pDifference);
this->HighlightCells(pDifference, fHLDesired, hlOff);
// Turn the newly selected cells on
DiffRgn(fSelections, pPreviousSelection, pDifference);
this->HighlightCells(pDifference, hlOff, fHLDesired);
}
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal void TGridView::SetSelectionRect(short left,
short top,
short right,
short bottom,
Boolean extendSelection,
Boolean highlight,
Boolean select)
{
if ((left == 0) && (top == 0) && (right == 0) && (bottom == 0))
SetEmptyRgn(fTempSelections);
else
SetRectRgn(fTempSelections, left, top, right + 1, bottom + 1);
this->SetSelection(fTempSelections, extendSelection, highlight, select);
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVNonRes
pascal void TGridView::SetSingleSelection(Boolean theSetting)
{
fSingleSelection = theSetting;
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal GridCell TGridView::VPointToCell(const VPoint& aPoint)
{
GridCell aCell(fRowHeights->FindItem(aPoint.v), fColWidths->FindItem(aPoint.h));
if ((aCell.h == 0) || (aCell.v == 0))
return gZeroPt;
else
return aCell;
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal GridCell TGridView::VPointToLastCell(const VPoint& aPoint)
{
GridCell aCell;
aCell.h = fColWidths->FindItem(aPoint.h);
if (aCell.h == 0) // If its invalid, return the last column
aCell.h = fNumOfCols;
aCell.v = fRowHeights->FindItem(aPoint.v);
if (aCell.v == 0) // If its invalid, return the last row
aCell.v = fNumOfRows;
return aCell;
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVFields
pascal void TGridView::Fields(TObject* obj) // override
{
obj->DoToField("TGridView", NULL, bClass);
obj->DoToField("fSelections", &fSelections, bRgnHandle);
obj->DoToField("fHLRegion", &fHLRegion, bRgnHandle);
obj->DoToField("fTempSelections", &fTempSelections, bRgnHandle);
obj->DoToField("fNumOfRows", &fNumOfRows, bInteger);
obj->DoToField("fRowHeights", &fRowHeights, bObject);
obj->DoToField("fNumOfCols", &fNumOfCols, bInteger);
obj->DoToField("fColWidths", &fColWidths, bObject);
obj->DoToField("fRowInset", &fRowInset, bInteger);
obj->DoToField("fColInset", &fColInset, bInteger);
obj->DoToField("fAdornRows", &fAdornRows, bBoolean);
obj->DoToField("fAdornCols", &fAdornCols, bBoolean);
obj->DoToField("fSingleSelection", &fSingleSelection, bBoolean);
inherited::Fields(obj);
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVOpen
pascal void TTextGridView::Initialize(void) // override
{
inherited::Initialize();
fTextStyle = gSystemStyle;
fLineHeight = 0; // ??? WHat should we do here?
fLineAscent = 0;
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVOpen
pascal void TTextGridView::ITextGridView(TDocument* itsDocument,
// Its document
TView* itsSuperView,
// Its parent view
const VPoint& itsLocation,
// Top, Left in parent's coords
const VPoint& itsSize,
SizeDeterminer itsHSizeDet,
SizeDeterminer itsVSizeDet,
// Size determiners
short numOfRows,
// Number of rows initially
short numOfCols,
// Number of columns initially
short rowHeight,
// Row height, or zero for font height
short colWidth,
// Width of items in the columns
Boolean adornRows,
// Adornment for Rows?
Boolean adornCols,
// Adornment for Columns?
short rowInset,
// horizontal space between cells
short colInset,
// vertical space between cells
Boolean singleSelection,
// single cell selection?
const TextStyle& itsTextStyle)// size, color, etc. font info
{
fTextStyle = itsTextStyle;
this->SetUpFont();
if (rowHeight == 0)
rowHeight = fLineHeight + rowInset;
this->IGridView(itsDocument, itsSuperView, itsLocation, itsSize, itsHSizeDet, itsVSizeDet, numOfRows, numOfCols, rowHeight, colWidth, adornRows, adornCols, rowInset, colInset, singleSelection);
if ((fNumOfCols == 1) && (fSizeDeterminer[hSel] != sizeFixed) && (this->GetColWidth(1) == 0) && (fSuperView != NULL))
this->SetColWidth(1, fNumOfCols, (short)fSuperView->fSize.h);//!!! Note cast
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVOpen
pascal void TTextGridView::IRes(TDocument* itsDocument,
TView* itsSuperView,
Ptr& itsParams) // override
{
TextStyle itsTextStyle;
// The ancestor will need to focus when adding rows or columns.
// Get the information necessary to focus since this class sets textStyle when focusing
fTextStyle = gSystemStyle; // Put in safe state
inherited::IRes(itsDocument, itsSuperView, itsParams);
{
TextGridViewTemplate& templateData = *((TextGridViewTemplate *) itsParams);
SetTextStyle(itsTextStyle, GetFontNum(templateData.itsFontName), templateData.itsFontFace, templateData.itsFontSize, templateData.itsFontColor);
}
fTextStyle = itsTextStyle;
this->SetUpFont();
if (fNumOfRows > 0)
if (this->GetRowHeight(1) == 0) // set row height from font
this->SetRowHeight(1, fNumOfRows, fLineHeight + fRowInset);
if ((fNumOfCols == 1) && (fSizeDeterminer[hSel] != sizeFixed) && (this->GetColWidth(1) == 0))
this->SetColWidth(1, fNumOfCols, (short)fSize.h);//!!! Note cast
OffsetPtrWStr(itsParams, sizeof(TextGridViewTemplate));
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal TObject* TTextGridView::Clone(void) // override
{
TTextGridView * aClonedTextGridView = (TTextGridView *)(inherited::Clone());
return aClonedTextGridView;
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVNonRes
pascal void TTextGridView::WRes(ViewRsrcHandle theResource,
Ptr& itsParams) // override
{
short theSize;
Str255 theFont;
inherited::WRes(theResource, itsParams);
theSize = fTextStyle.tsSize;
GetPortFontInfo(fTextStyle.tsFont, theFont, theSize);
TextGridViewTemplate& templateData = *((TextGridViewTemplate *) ExpandPtrWStr((Handle)theResource, itsParams, sizeof(TextGridViewTemplate), theFont.Length()));
templateData.itsFontFace = fTextStyle.tsFace;
templateData.itsFontSize = theSize;
templateData.itsFontColor = fTextStyle.tsColor;
// templateData.itsFontName = theFont;
CopyStr255(theFont, PRStr(templateData.itsFontName));
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVNonRes
pascal void TTextGridView::WriteRes(ViewRsrcHandle theResource,
Ptr& itsParams)// override
{
gWResSignature = 'txtg';
gWResType = "TTextGridView";
this->WRes(theResource, itsParams);
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal void TTextGridView::DrawCell(GridCell aCell,
const VRect& aRect)// override
{
Str255 theText;
Rect r;
this->GetText(aCell, theText);
if (this->GetColWidth(aCell.h) > 0)
{
this->ViewToQDRect(aRect, r);
MADrawString(theText, r, teFlushDefault);
}
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal Boolean TTextGridView::Focus(void) // override
{
if (inherited::Focus())
{
this->SetPen();
return TRUE;
}
else
return FALSE;
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVOpen
pascal void TTextGridView::SetUpFont(void)
{
GrafPtr savedPort;
FontInfo theFontInfo;
GetPort(savedPort);
SetPort(gWorkPort);
this->SetPen();
fLineHeight = MAGetFontInfo(theFontInfo); // returns height of font
fLineAscent = theFontInfo.ascent + (theFontInfo.leading / 2);
SetPort(savedPort);
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal void TTextGridView::SetPen(void)
{
TextStyle itsTextStyle = fTextStyle;
SetPortTextStyle(itsTextStyle);
PenNormal();
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal void TTextGridView::GetText(GridCell /* aCell */,
Str255& /* aString */)
{
this->SubClassResponsibility();
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVFields
pascal void TTextGridView::Fields(TObject* obj) // override
{
obj->DoToField("TTextGridView", NULL, bClass);
obj->DoToField("fLineHeight", &fLineHeight, bInteger);
obj->DoToField("fLineAscent", &fLineAscent, bInteger);
obj->DoToField("fTextStyle", &fTextStyle, bTextStyle);
inherited::Fields(obj);
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVOpen
pascal void TTextListView::Initialize(void) // override
{
inherited::Initialize();
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVOpen
pascal void TTextListView::ITextListView(TDocument* itsDocument,
// Its document
TView* itsSuperView,
// Its parent view
const VPoint& itsLocation,
// Top, Left in parent's coords
const VPoint& itsSize,
SizeDeterminer itsHSizeDet,
SizeDeterminer itsVSizeDet,
// Size determiners
short numOfItems,
// Number of items initially
short rowHeight,
// Row height, or zero for font height
short colWidth,
// Width of items in the columns
Boolean adornRows,
// Draw the row adornments?
Boolean adornCols,
// Draw the col adornment?
short rowInset,
// Amount to inset the rows
short colInset,
// Amount to inset the column
Boolean singleSelection,
// single cell selection?
const TextStyle& itsTextStyle)// size, color, etc. font info
{
this->ITextGridView(itsDocument, itsSuperView, itsLocation, itsSize, itsHSizeDet, itsVSizeDet, numOfItems, 1, rowHeight, colWidth, adornRows, adornCols, rowInset, colInset, singleSelection, itsTextStyle);
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal TObject* TTextListView::Clone(void) // override
{
TTextListView * aClonedTextListView = (TTextListView *)(inherited::Clone());
return aClonedTextListView;
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVNonRes
pascal void TTextListView::WriteRes(ViewRsrcHandle theResource,
Ptr& itsParams)// override
{
gWResSignature = 'lstg';
gWResType = "TTextListView";
this->WRes(theResource, itsParams);
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal void TTextListView::AllItemsDo(pascal void(* DoToItem)(short anItem,
void* staticLink),
void* staticLink)
{
this->EachItemDo(1, fNumOfRows, DoToItem, staticLink);
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal Boolean TTextListView::CanSelectCell(GridCell aCell)// override
{
return (inherited::CanSelectCell(aCell) && this->CanSelectItem(aCell.v));
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal Boolean TTextListView::CanSelectItem(short anItem)
{
return ((anItem >= 1) && (anItem <= fNumOfRows));
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVNonRes
pascal void TTextListView::DelItemAt(short anItem,
short numOfItems)
{
this->DelRowAt(anItem, numOfItems);
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVNonRes
pascal void TTextListView::DelItemFirst(short numOfItems)
{
this->DelItemAt(1, numOfItems);
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVNonRes
pascal void TTextListView::DelItemLast(short numOfItems)
{
this->DelItemAt(fNumOfRows - numOfItems + 1, numOfItems);
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal void TTextListView::EachItemDo(short start,
short stop,
pascal void(* DoToItem)(short anItem,
void* staticLink),
void* staticLink)
{
for (short i = start; i <= stop; ++i)
DoToItem(i, staticLink);
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
// Iteration class to replace nested routine
class CDoToCell
{
const DoToItemType& fDoToItem;
const void*& fStaticLink;
public:
// Constructor
CDoToCell(const DoToItemType& DoToItem,
const void*& staticLink) :
fDoToItem(DoToItem),
fStaticLink(staticLink)
{
}
pascal void DoToCell(GridCell aCell);
};
#pragma segment GVRes
pascal void CDoToCell::DoToCell(GridCell aCell)
{
fDoToItem(aCell.v, fStaticLink);
}
#pragma segment GVRes
pascal void TTextListView::EachSelectedItemDo(DoToItemType DoToItem,
void* staticLink)
{
CDoToCell aCDoToCell(DoToItem, staticLink);
this->EachInRgn(fSelections, (DoToCellType) & CDoToCell::DoToCell, &aCDoToCell);
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal short TTextListView::FirstSelectedItem(void)
{
GridCell aGridCell(this->FirstSelectedCell());
return aGridCell.v;
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal short TTextListView::GetItemHeight(short anItem)
{
return this->GetRowHeight(anItem);
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal short TTextListView::GetItemWidth(void)
{
return this->GetColWidth(1);
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal void TTextListView::GetItemText(short /* anItem */,
Str255& /* aString */)
{
this->SubClassResponsibility();
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal void TTextListView::GetText(GridCell aCell,
Str255& aString)// override
{
this->GetItemText(aCell.v, aString);
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal void TTextListView::InsItemBefore(short anItem,
short numOfItems)
{
this->InsRowBefore(anItem, numOfItems, fLineHeight + fRowInset);
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal void TTextListView::InsItemFirst(short numOfItems)
{
this->InsItemBefore(1, numOfItems);
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal void TTextListView::InsItemLast(short numOfItems)
{
this->InsItemBefore(fNumOfRows + 1, numOfItems);
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal void TTextListView::InvalidateItem(short anItem)
{
GridCell aCell(anItem, 1);
this->InvalidateCell(aCell);
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal Boolean TTextListView::IsItemSelected(short anItem)
{
GridCell aCell(anItem, 1);
return this->IsCellSelected(aCell);
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal short TTextListView::LastSelectedItem(void)
{
GridCell aGridCell(this->LastSelectedCell());
return aGridCell.v;
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVNonRes
pascal void TTextListView::Resize(const VPoint& newSize,
Boolean invalidate)// override
{
inherited::Resize(newSize, invalidate);
if (fNumOfCols == 1)
{
fColWidths->fTotal = fColWidths->fTotal - (*(fColWidths->fChunks))[0].value + newSize.h;
(*(fColWidths->fChunks))[0].value = (short)newSize.h;//!!! Note cast
}
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal void TTextListView::SelectCell(GridCell theCell,
Boolean extendSelection,
Boolean highlight,
Boolean select)// override
{
this->SelectItem(theCell.v, extendSelection, highlight, select);
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVRes
pascal void TTextListView::SelectItem(short anItem,
Boolean extendSelection,
Boolean highlight,
Boolean select)
{
GridCell aCell(anItem, (short)Min(1, anItem));
inherited::SelectCell(aCell, extendSelection, highlight, select);
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVNonRes
pascal void TTextListView::SetItemHeight(short anItem,
short numOfItems,
short aHeight)
{
this->SetRowHeight(anItem, numOfItems, aHeight);
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVNonRes
pascal void TTextListView::SetItemWidth(short aWidth)
{
this->SetColWidth(1, 1, aWidth);
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVFields
pascal void TTextListView::Fields(TObject* obj) // override
{
obj->DoToField("TTextListView", (Ptr)NULL, bClass);
inherited::Fields(obj);
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVSelCommand
pascal void TCellSelectCommand::Initialize(void)// override
{
inherited::Initialize();
fAnchorCell = gZeroPt; // At least set it to something
fCmdKey = FALSE;
fDeselecting = FALSE;
fDifference = NULL;
fGridView = NULL;
fPrevCell = Point(-1, -1);
fPrevSelection = NULL;
fShiftKey = FALSE;
fThisSelection = NULL;
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVSelCommand
pascal void TCellSelectCommand::ICellSelectCommand(TGridView* itsView,
const VPoint& itsMouse,
Boolean theShiftKey,
Boolean theCmdKey)
{
FailInfo fi;
this->INoChangesTracker(cNoCommand, NULL, itsView, itsView->GetScroller(FALSE), itsMouse);
fShiftKey = theShiftKey;
fCmdKey = theCmdKey;
fViewConstrain = FALSE;
fGridView = itsView;
if (fi.Try())
{
fPrevSelection = MakeNewRgn();
CopyRgn(fGridView->fSelections, fPrevSelection);
fThisSelection = fGridView->fHLRegion;
SetEmptyRgn(fThisSelection);
fDifference = MakeNewRgn();
fi.Success();
}
else // Recover
{
this->Free();
fi.ReSignal();
}
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVDoCommand
pascal void TCellSelectCommand::Free(void) // override
{
fPrevSelection = DisposeIfRgnHandle(fPrevSelection);
fDifference = DisposeIfRgnHandle(fDifference);
fThisSelection = NULL; /* I don't own it so I don't dispose it. But,
I sure don't need a reference to it any
more. */
inherited::Free();
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVDoCommand
pascal void TCellSelectCommand::ComputeAnchorCell(GridCell& clickedCell)
{
fAnchorCell = clickedCell;
if (fShiftKey && (!EmptyRgn(fPrevSelection)))
{
Rect & bounds = (**fPrevSelection).rgnBBox;
if (fAnchorCell.h >= bounds.left)
fAnchorCell.h = bounds.left;
else
fAnchorCell.h = bounds.right - 1;
if (fAnchorCell.v >= bounds.top)
fAnchorCell.v = bounds.top;
else
fAnchorCell.v = bounds.bottom - 1;
}
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVDoCommand
pascal void TCellSelectCommand::ComputeNewSelection(GridCell& clickedCell)
{
Rect r;
if (fGridView->CanSelectCell(clickedCell))
{
if (fGridView->fSingleSelection || (!fShiftKey))
SetRect(r, clickedCell.h, clickedCell.v, clickedCell.h + 1, clickedCell.v + 1);
else
{
Pt2Rect(fAnchorCell, clickedCell, r);
++r.right;
++r.bottom;
}
RectRgn(fThisSelection, r);
if (fCmdKey && (!fGridView->fSingleSelection))
if (fDeselecting)
DiffRgn(fPrevSelection, fThisSelection, fThisSelection);
else
UnionRgn(fPrevSelection, fThisSelection, fThisSelection);
}
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVDoCommand
pascal void TCellSelectCommand::HighlightNewSelection(void)
{
// Turn off previously selected cells
DiffRgn(fPrevSelection, fThisSelection, fDifference);
fGridView->HighlightCells(fDifference, fGridView->fHLDesired, hlOff);
// Turn on newly selected cells
DiffRgn(fThisSelection, fPrevSelection, fDifference);
fGridView->HighlightCells(fDifference, hlOff, fGridView->fHLDesired);
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVDoCommand
pascal void TCellSelectCommand::TrackFeedback(TrackPhase /* aTrackPhase */,
const VPoint& /* anchorPoint */,
const VPoint& /* previousPoint */,
const VPoint& /* nextPoint */,
Boolean /* mouseDidMove */,
Boolean /* turnItOn */)// override
{
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVDoCommand
pascal TTracker* TCellSelectCommand::TrackMouse(TrackPhase aTrackPhase,
VPoint&/* anchorPoint */ ,
VPoint&/* previousPoint */ ,
VPoint& nextPoint,
Boolean mouseDidMove)// override
{
GridCell clickedCell;
VRect viewExtent;
VPoint clippedPoint;
if (mouseDidMove)
{
fGridView->GetExtent(viewExtent);
clippedPoint = nextPoint;
clippedPoint.ConstrainTo(viewExtent);
clickedCell = fGridView->VPointToCell(clippedPoint);
if (aTrackPhase == trackBegin)
{
this->ComputeAnchorCell(clickedCell);
if (fCmdKey)
fDeselecting = PtInRgn(fAnchorCell, fGridView->fSelections);
}
if (clickedCell != fPrevCell)
{
this->ComputeNewSelection(clickedCell);
this->HighlightNewSelection();
CopyRgn(fThisSelection, fPrevSelection);
fPrevCell = clickedCell;
}
}
return this;
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVDoCommand
pascal void TCellSelectCommand::DoIt(void) // override
{
if (fGridView->fSingleSelection)
fGridView->SelectCell((*fThisSelection)->rgnBBox[topLeft], kDontExtend, kDontHighlight, kSelect);
else
fGridView->SetSelection(fThisSelection, kDontExtend, kDontHighlight, kSelect);
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVFields
pascal void TCellSelectCommand::Fields(TObject* obj)// override
{
obj->DoToField("TCellSelectCommand", NULL, bClass);
obj->DoToField("fGridView", &fGridView, bObject);
obj->DoToField("fShiftKey", &fShiftKey, bBoolean);
obj->DoToField("fCmdKey", &fCmdKey, bBoolean);
obj->DoToField("fDeselecting", &fDeselecting, bBoolean);
obj->DoToField("fAnchorCell", &fAnchorCell, bPoint);
obj->DoToField("fPrevCell", &fPrevCell, bPoint);
obj->DoToField("fThisSelection", &fThisSelection, bRgnHandle);
obj->DoToField("fPrevSelection", &fPrevSelection, bRgnHandle);
obj->DoToField("fDifference", &fDifference, bRgnHandle);
inherited::Fields(obj);
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVDoCommand
pascal void TRCSelectCommand::ComputeNewSelection(GridCell& clickedCell)// override
{
Rect r;
if (fGridView->CanSelectCell(clickedCell))
{
if (fGridView->fSingleSelection)
r = Rect(clickedCell.v, clickedCell.h, clickedCell.v + 1, clickedCell.h + 1);
else
{
Pt2Rect(fAnchorCell, clickedCell, r);
++r.right;
++r.bottom;
}
RectRgn(fThisSelection, r);
if (fCmdKey && (!fGridView->fSingleSelection))
if (fDeselecting)
DiffRgn(fPrevSelection, fThisSelection, fThisSelection);
else
UnionRgn(fPrevSelection, fThisSelection, fThisSelection);
}
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVDoCommand
pascal TTracker* TRCSelectCommand::TrackMouse(TrackPhase aTrackPhase,
VPoint&/* anchorPoint */ ,
VPoint&/* previousPoint */ ,
VPoint& nextPoint,
Boolean mouseDidMove)// override
{
GridCell clickedCell;
VRect viewExtent;
VPoint clippedPoint;
if (mouseDidMove)
{
fGridView->GetExtent(viewExtent);
clippedPoint = nextPoint;
clippedPoint.ConstrainTo(viewExtent);
clickedCell = fGridView->VPointToCell(clippedPoint);
if (aTrackPhase == trackBegin)
{
this->ComputeAnchorCell(clickedCell);
if (fCmdKey)
fDeselecting = PtInRgn(fAnchorCell, fGridView->fSelections);
}
if (clickedCell != fPrevCell)
{
if (!fShiftKey && (aTrackPhase != trackBegin))
{
this->ComputeAnchorCell(clickedCell);
if (fCmdKey)
fDeselecting = PtInRgn(fAnchorCell, fGridView->fSelections);
}
this->ComputeNewSelection(clickedCell);
this->HighlightNewSelection();
CopyRgn(fThisSelection, fPrevSelection);
fPrevCell = clickedCell;
}
}
return this;
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVFields
pascal void TRCSelectCommand::Fields(TObject* obj)// override
{
obj->DoToField("TRCSelectCommand", (Ptr)NULL, bClass);
inherited::Fields(obj);
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVSelCommand
pascal void TRowSelectCommand::IRowSelectCommand(TGridView* itsView,
const VPoint& itsMouse,
Boolean theShiftKey,
Boolean theCmdKey)
{
this->ICellSelectCommand(itsView, itsMouse, theShiftKey, theCmdKey);
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVDoCommand
pascal void TRowSelectCommand::ComputeAnchorCell(GridCell& clickedCell)// override
{
inherited::ComputeAnchorCell(clickedCell);
fAnchorCell.h = 1;
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVDoCommand
pascal void TRowSelectCommand::ComputeNewSelection(GridCell& clickedCell)// override
{
clickedCell.h = fGridView->fNumOfCols;
inherited::ComputeNewSelection(clickedCell);
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVFields
pascal void TRowSelectCommand::Fields(TObject* obj)// override
{
obj->DoToField("TRowSelectCommand", (Ptr)NULL, bClass);
inherited::Fields(obj);
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVSelCommand
pascal void TColumnSelectCommand::IColumnSelectCommand(TGridView* itsView,
const VPoint& itsMouse,
Boolean theShiftKey,
Boolean theCmdKey)
{
this->ICellSelectCommand(itsView, itsMouse, theShiftKey, theCmdKey);
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVDoCommand
pascal void TColumnSelectCommand::ComputeAnchorCell(GridCell& clickedCell)// override
{
inherited::ComputeAnchorCell(clickedCell);
fAnchorCell.v = 1;
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVDoCommand
pascal void TColumnSelectCommand::ComputeNewSelection(GridCell& clickedCell)// override
{
clickedCell.v = fGridView->fNumOfRows;
inherited::ComputeNewSelection(clickedCell);
}
//--------------------------------------------------------------------------------------------------
#pragma segment GVFields
pascal void TColumnSelectCommand::Fields(TObject* obj)// override
{
obj->DoToField("TColumnSelectCommand", (Ptr)NULL, bClass);
inherited::Fields(obj);
}